/**
 * @file facelib.cpp
 * @author lynxi
 * @brief
 * @version 1.0
 * @date 2024-04-30
 *
 * Copyright:
 * © 2024 北京灵汐科技有限公司 版权所有。
 * 注意：以下内容均为北京灵汐科技有限公司原创，未经本公司允许，不得转载，否则将视为侵权；对于不遵守此声明或者其他违法使用以下内容者，本公司依法保留追究权。
 * © 2024 Lynxi Technologies Co., Ltd. All rights reserved.
 * NOTICE: All information contained here is, and remains the property of Lynxi.
 * This file can not be copied or distributed without the permission of Lynxi
 * Technologies Co., Ltd.
 *
 */

#pragma once

#include <lyn_api.h>
#include <iostream>
#include "ipeParam.h"
#include "util.hpp"

class IpeParamFace : public IpeParamBase {
 public:
  IpeParamFace(int iModelWidth, int iModelHeight)
      : IpeParamBase(iModelWidth, iModelHeight) {}
  ~IpeParamFace() {}

  // IPE处理
  virtual void CalcParam(lynStream_t stream, void *inputData,
                         void *outputData) {
    // 结构体reset
    CHECK_ERR(lynIpeResetPicDesc(m_oPicDescIn));
    CHECK_ERR(lynIpeResetPicDesc(m_oPicDescOut));
    CHECK_ERR(lynIpeResetConfigDesc(m_oConfigDesc));
    CHECK_ERR(lynIpeSetInputPicDesc(m_oPicDescIn, inputData, m_iImgWidth,
                                    m_iImgHeight, m_format));
    CHECK_ERR(lynIpeSetOutputPicData(m_oPicDescOut, outputData));
    CHECK_ERR(lynIpeSetC2CConfig(m_oConfigDesc, LYN_PIX_FMT_RGB24, 0));
    CHECK_ERR(
        lynIpeSetResizeConfig(m_oConfigDesc, m_iResizeWidth, m_iResizeHeight));
    CHECK_ERR(lynIpeSetPadConfig(m_oConfigDesc, 0, m_iPadRight, m_iPadBottom, 0,
                                 114, 114, 114));
    CHECK_ERR(
        lynIpeCalOutputPicDesc(m_oPicDescOut, m_oPicDescIn, m_oConfigDesc, 2));
    CHECK_ERR(
        lynIpeProcessAsync(stream, m_oPicDescIn, m_oPicDescOut, m_oConfigDesc));
  }

  virtual void SetImgInfo(int32_t width, int32_t height,
                          lynPixelFormat_t format) {

    double scale = (double)width / (double)m_iModelWidth > (double)height / (double)m_iModelHeight
                       ? (double)width / (double)m_iModelWidth
                       : (double)height / (double)m_iModelHeight;
    m_iResizeWidth = int((double)width / scale) & ~1;
    m_iResizeHeight = int((double)height / scale) & ~1;
    if (m_iResizeWidth > 1920) {
      m_iResizeWidth = 1920;
    }
    if (m_iResizeHeight > 1080) {
      m_iResizeHeight = 1080;
    }

    m_iPadRight = m_iModelWidth - m_iResizeWidth;
    m_iPadBottom = m_iModelHeight - m_iResizeHeight;

    IpeParamBase::SetImgInfo(width, height, format);
  }

 private:
  // 图片resize参数
  int m_iResizeWidth = 0;
  int m_iResizeHeight = 0;
  // 图片填充参数
  int m_iPadBottom = 0;
  int m_iPadRight = 0;
};

class IpeParamW600k_mbf : public IpeParamBase {
 public:
  IpeParamW600k_mbf(int iModelWidth, int iModelHeight)
      : IpeParamBase(iModelWidth, iModelHeight) {}
  ~IpeParamW600k_mbf() {}

  // IPE处理
  virtual void CalcParam(lynStream_t stream, void *inputData,
                         void *outputData) {
    // 结构体reset
    CHECK_ERR(lynIpeResetPicDesc(m_oPicDescIn));
    CHECK_ERR(lynIpeResetPicDesc(m_oPicDescOut));
    CHECK_ERR(lynIpeResetConfigDesc(m_oConfigDesc));
    CHECK_ERR(lynIpeSetInputPicDesc(m_oPicDescIn, inputData, m_iImgWidth,
                                    m_iImgHeight, m_format));
    CHECK_ERR(lynIpeSetOutputPicData(m_oPicDescOut, outputData));
    CHECK_ERR(lynIpeSetC2CConfig(m_oConfigDesc, LYN_PIX_FMT_RGB24, 0));
    CHECK_ERR(
        lynIpeSetResizeConfig(m_oConfigDesc, m_iModelWidth, m_iModelHeight));
    CHECK_ERR(
        lynIpeCalOutputPicDesc(m_oPicDescOut, m_oPicDescIn, m_oConfigDesc, 2));
    CHECK_ERR(
        lynIpeProcessAsync(stream, m_oPicDescIn, m_oPicDescOut, m_oConfigDesc));
  }
};

class IpeParamCrop : public IpeParamBase {
 public:
  IpeParamCrop(int x, int y, int w, int h)
      : IpeParamBase(0, 0), m_x(x), m_y(y), m_w(w), m_h(h) {}
  ~IpeParamCrop() {}

  // IPE处理
  virtual void CalcParam(lynStream_t stream, void *inputData,
                         void *outputData) {
    // 结构体reset
    CHECK_ERR(lynIpeResetPicDesc(m_oPicDescIn));
    CHECK_ERR(lynIpeResetPicDesc(m_oPicDescOut));
    CHECK_ERR(lynIpeResetConfigDesc(m_oConfigDesc));
    CHECK_ERR(lynIpeSetInputPicDesc(m_oPicDescIn, inputData, m_iImgWidth,
                                    m_iImgHeight, m_format));
    CHECK_ERR(lynIpeSetOutputPicData(m_oPicDescOut, outputData));
    CHECK_ERR(lynIpeSetCropConfig(m_oConfigDesc, m_x, m_y, m_w, m_h));
    CHECK_ERR(lynIpeSetC2CConfig(m_oConfigDesc, LYN_PIX_FMT_RGB24, 0));
    CHECK_ERR(
        lynIpeCalOutputPicDesc(m_oPicDescOut, m_oPicDescIn, m_oConfigDesc, 0));
    CHECK_ERR(
        lynIpeProcessAsync(stream, m_oPicDescIn, m_oPicDescOut, m_oConfigDesc));
  }

 private:
  int m_x;
  int m_y;
  int m_w;
  int m_h;
};

class IpeParamAffine : public IpeParamBase {
 public:
  IpeParamAffine(int iModelWidth, int iModelHeight, float (*matrix)[3],
                 uint8_t xColor, uint8_t yColor, uint8_t zColor)
      : IpeParamBase(iModelWidth, iModelHeight),
        m_xColor(xColor),
        m_yColor(yColor),
        m_zColor(zColor) {
    m_matrix = reinterpret_cast<float *>(matrix);
  }
  ~IpeParamAffine() {}

  // IPE处理
  virtual void CalcParam(lynStream_t stream, void *inputData,
                         void *outputData) {
    // 结构体reset
    CHECK_ERR(lynIpeResetPicDesc(m_oPicDescIn));
    CHECK_ERR(lynIpeResetPicDesc(m_oPicDescOut));
    CHECK_ERR(lynIpeResetConfigDesc(m_oConfigDesc));
    CHECK_ERR(lynIpeSetInputPicDesc(m_oPicDescIn, inputData, m_iImgWidth,
                                    m_iImgHeight, m_format));
    CHECK_ERR(lynIpeSetOutputPicData(m_oPicDescOut, outputData));
    CHECK_ERR(lynIpeSetOutputPicDesc(m_oPicDescOut, outputData, m_iModelWidth,
                                     m_iModelHeight, LYN_PIX_FMT_RGB24));
    CHECK_ERR(lynIpeSetAffineConfig(m_oConfigDesc,
                                    reinterpret_cast<float(*)[3]>(m_matrix),
                                    m_xColor, m_yColor, m_zColor));
    CHECK_ERR(
        lynIpeProcessAsync(stream, m_oPicDescIn, m_oPicDescOut, m_oConfigDesc));
  }

 private:
  float *m_matrix;
  uint8_t m_xColor;
  uint8_t m_yColor;
  uint8_t m_zColor;
};
